home *** CD-ROM | disk | FTP | other *** search
- """Edit the Python Preferences file."""
- #
- # This program is getting more and more clunky. It should really
- # be rewritten in a modeless way some time soon.
-
- from Dlg import *
- from Events import *
- from Res import *
- import string
- import struct
- import macfs
- import MacOS
- import os
- import sys
- import Res # For Res.Error
-
- # Resource in the Python resource chain
- PREFNAME_NAME="PythonPreferenceFileName"
-
- # resource IDs in our own resources (dialogs, etc)
- MESSAGE_ID = 256
-
- DIALOG_ID = 511
- TEXT_ITEM = 1
- OK_ITEM = 2
- CANCEL_ITEM = 3
- DIR_ITEM = 4
- TITLE_ITEM = 5
- OPTIONS_ITEM = 7
-
- # The options dialog. There is a correspondence between
- # the dialog item numbers and the option.
- OPT_DIALOG_ID = 510
- # 1 thru 9 are the options
- # The GUSI creator/type and delay-console
- OD_CREATOR_ITEM = 10
- OD_TYPE_ITEM = 11
- OD_DELAYCONSOLE_ITEM = 12
- OD_OK_ITEM = 13
- OD_CANCEL_ITEM = 14
-
- # Resource IDs in the preferences file
- PATH_STRINGS_ID = 128
- DIRECTORY_ID = 128
- OPTIONS_ID = 128
- GUSI_ID = 10240
-
- # Override IDs (in the applet)
- OVERRIDE_PATH_STRINGS_ID = 129
- OVERRIDE_DIRECTORY_ID = 129
- OVERRIDE_OPTIONS_ID = 129
- OVERRIDE_GUSI_ID = 10241
-
- # Things we know about the GUSI resource. Note the code knows these too.
- GUSIPOS_TYPE=0
- GUSIPOS_CREATOR=4
- GUSIPOS_SKIP=8
- GUSIPOS_FLAGS=9
- GUSIPOS_VERSION=10
- GUSIVERSION='0181'
- GUSIFLAGS_DELAY=0x20 # Mask
-
- READ = 1
- WRITE = 2
- smAllScripts = -3
- kOnSystemDisk = 0x8000
-
- def restolist(data):
- """Convert STR# resource data to a list of strings"""
- if not data:
- return []
- num, = struct.unpack('h', data[:2])
- data = data[2:]
- rv = []
- for i in range(num):
- strlen = ord(data[0])
- if strlen < 0: strlen = strlen + 256
- str = data[1:strlen+1]
- data = data[strlen+1:]
- rv.append(str)
- return rv
-
- def listtores(list):
- """Convert a list of strings to STR# resource data"""
- rv = struct.pack('h', len(list))
- for str in list:
- rv = rv + chr(len(str)) + str
- return rv
-
- def message(str = "Hello, world!", id = MESSAGE_ID):
- """Show a simple alert with a text message"""
- d = GetNewDialog(id, -1)
- d.SetDialogDefaultItem(1)
- tp, h, rect = d.GetDialogItem(2)
- SetDialogItemText(h, str)
- while 1:
- n = ModalDialog(None)
- if n == 1: break
-
- def optinteract((options, creator, type, delaycons)):
- """Let the user interact with the options dialog"""
- old_options = (options[:], creator, type, delaycons)
- d = GetNewDialog(OPT_DIALOG_ID, -1)
- tp, h, rect = d.GetDialogItem(OD_CREATOR_ITEM)
- SetDialogItemText(h, creator)
- tp, h, rect = d.GetDialogItem(OD_TYPE_ITEM)
- SetDialogItemText(h, type)
- d.SetDialogDefaultItem(OD_OK_ITEM)
- d.SetDialogCancelItem(OD_CANCEL_ITEM)
- while 1:
- for i in range(len(options)):
- tp, h, rect = d.GetDialogItem(i+1)
- h.as_Control().SetControlValue(options[i])
- tp, h, rect = d.GetDialogItem(OD_DELAYCONSOLE_ITEM)
- h.as_Control().SetControlValue(delaycons)
- n = ModalDialog(None)
- if n == OD_OK_ITEM:
- tp, h, rect = d.GetDialogItem(OD_CREATOR_ITEM)
- ncreator = GetDialogItemText(h)
- tp, h, rect = d.GetDialogItem(OD_TYPE_ITEM)
- ntype = GetDialogItemText(h)
- if len(ncreator) == 4 and len(ntype) == 4:
- return options, ncreator, ntype, delaycons
- else:
- sys.stderr.write('\007')
- elif n == OD_CANCEL_ITEM:
- return old_options
- elif n in (OD_CREATOR_ITEM, OD_TYPE_ITEM):
- pass
- elif n == OD_DELAYCONSOLE_ITEM:
- delaycons = (not delaycons)
- elif 1 <= n <= len(options):
- options[n-1] = (not options[n-1])
-
-
- def interact(list, pythondir, options, title):
- """Let the user interact with the dialog"""
- opythondir = pythondir
- try:
- # Try to go to the "correct" dir for GetDirectory
- os.chdir(pythondir.as_pathname())
- except os.error:
- pass
- d = GetNewDialog(DIALOG_ID, -1)
- tp, h, rect = d.GetDialogItem(TITLE_ITEM)
- SetDialogItemText(h, title)
- tp, h, rect = d.GetDialogItem(TEXT_ITEM)
- SetDialogItemText(h, string.joinfields(list, '\r'))
- ## d.SetDialogDefaultItem(OK_ITEM)
- d.SetDialogCancelItem(CANCEL_ITEM)
- while 1:
- n = ModalDialog(None)
- if n == OK_ITEM:
- break
- if n == CANCEL_ITEM:
- return None
- ## if n == REVERT_ITEM:
- ## return [], pythondir
- if n == DIR_ITEM:
- fss, ok = macfs.GetDirectory('Select python home folder:')
- if ok:
- pythondir = fss
- if n == OPTIONS_ITEM:
- options = optinteract(options)
- tmp = string.splitfields(GetDialogItemText(h), '\r')
- rv = []
- for i in tmp:
- if i:
- rv.append(i)
- return rv, pythondir, options
-
- def getprefpath(id):
- # Load the path and directory resources
- try:
- sr = GetResource('STR#', id)
- except (MacOS.Error, Res.Error):
- return None, None
- d = sr.data
- l = restolist(d)
- return l, sr
-
- def getprefdir(id):
- try:
- dr = GetResource('alis', id)
- fss, fss_changed = macfs.RawAlias(dr.data).Resolve()
- except (MacOS.Error, Res.Error):
- return None, None, 1
- return fss, dr, fss_changed
-
- def getoptions(id):
- try:
- opr = GetResource('Popt', id)
- except (MacOS.Error, Res.Error):
- return [0]*9, None
- options = map(lambda x: ord(x), opr.data)
- while len(options) < 9:
- options = options + [0]
- return options, opr
-
- def getgusioptions(id):
- try:
- opr = GetResource('GU\267I', id)
- except (MacOS.Error, Res.Error):
- return '????', '????', 0, None
- data = opr.data
- type = data[GUSIPOS_TYPE:GUSIPOS_TYPE+4]
- creator = data[GUSIPOS_CREATOR:GUSIPOS_CREATOR+4]
- flags = ord(data[GUSIPOS_FLAGS])
- version = data[GUSIPOS_VERSION:GUSIPOS_VERSION+4]
- if version <> GUSIVERSION:
- message('GU\267I resource version "%s", fixing to "%s"'%(version, GUSIVERSION))
- flags = 0
- delay = (not not (flags & GUSIFLAGS_DELAY))
- return creator, type, delay, opr
-
- def setgusioptions(opr, creator, type, delay):
- data = opr.data
- flags = ord(data[GUSIPOS_FLAGS])
- version = data[GUSIPOS_VERSION:GUSIPOS_VERSION+4]
- if version <> GUSIVERSION:
- flags = 0x88
- version = GUSIVERSION
- if delay:
- flags = flags | GUSIFLAGS_DELAY
- else:
- flags = flags & ~GUSIFLAGS_DELAY
- data = type + creator + data[GUSIPOS_SKIP] + chr(flags) + GUSIVERSION + data[GUSIPOS_VERSION+4:]
- return data
-
- def openpreffile(rw):
- # Find the preferences folder and our prefs file, create if needed.
- vrefnum, dirid = macfs.FindFolder(kOnSystemDisk, 'pref', 0)
- try:
- pnhandle = GetNamedResource('STR ', PREFNAME_NAME)
- except Res.Error:
- message("No %s resource (old Python?)"%PREFNAME_NAME)
- sys.exit(1)
- prefname = pnhandle.data[1:]
- preff_fss = macfs.FSSpec((vrefnum, dirid, prefname))
- try:
- preff_handle = FSpOpenResFile(preff_fss, rw)
- except Res.Error:
- # Create it
- message('No preferences file, creating one...')
- FSpCreateResFile(preff_fss, 'Pyth', 'pref', smAllScripts)
- preff_handle = FSpOpenResFile(preff_fss, rw)
- return preff_handle
-
- def openapplet(name):
- fss = macfs.FSSpec(name)
- try:
- app_handle = FSpOpenResFile(fss, WRITE)
- except Res.Error:
- message('File does not have a resource fork.')
- sys.exit(0)
- return app_handle
-
-
- def edit_preferences():
- preff_handle = openpreffile(WRITE)
-
- l, sr = getprefpath(PATH_STRINGS_ID)
- if l == None:
- message('Cannot find any sys.path resource! (Old python?)')
- sys.exit(0)
-
- fss, dr, fss_changed = getprefdir(DIRECTORY_ID)
- if fss == None:
- fss = macfs.FSSpec(os.getcwd())
- fss_changed = 1
-
- options, opr = getoptions(OPTIONS_ID)
- saved_options = options[:]
-
- creator, type, delaycons, gusi_opr = getgusioptions(GUSI_ID)
- saved_gusi_options = creator, type, delaycons
-
- # Let the user play away
- result = interact(l, fss, (options, creator, type, delaycons),
- 'System-wide preferences')
-
- # See what we have to update, and how
- if result == None:
- sys.exit(0)
-
- pathlist, nfss, (options, creator, type, delaycons) = result
- if nfss != fss:
- fss_changed = 1
-
- if fss_changed:
- alias = nfss.NewAlias()
- if dr:
- dr.data = alias.data
- dr.ChangedResource()
- else:
- dr = Resource(alias.data)
- dr.AddResource('alis', DIRECTORY_ID, '')
-
- if pathlist != l:
- if pathlist == []:
- if sr.HomeResFile() == preff_handle:
- sr.RemoveResource()
- elif sr.HomeResFile() == preff_handle:
- sr.data = listtores(pathlist)
- sr.ChangedResource()
- else:
- sr = Resource(listtores(pathlist))
- sr.AddResource('STR#', PATH_STRINGS_ID, '')
-
- if options != saved_options:
- newdata = reduce(lambda x, y: x+chr(y), options, '')
- if opr and opr.HomeResFile() == preff_handle:
- opr.data = newdata
- opr.ChangedResource()
- else:
- opr = Resource(newdata)
- opr.AddResource('Popt', OPTIONS_ID, '')
-
- if (creator, type, delaycons) != saved_gusi_options:
- newdata = setgusioptions(gusi_opr, creator, type, delaycons)
- if gusi_opr.HomeResFile() == preff_handle:
- gusi_opr.data = newdata
- gusi_opr.ChangedResource()
- else:
- ngusi_opr = Resource(newdata)
- ngusi_opr.AddResource('GU\267I', GUSI_ID, '')
-
- CloseResFile(preff_handle)
-
- def edit_applet(name):
- pref_handle = openpreffile(READ)
- app_handle = openapplet(name)
-
- notfound = ''
- l, sr = getprefpath(OVERRIDE_PATH_STRINGS_ID)
- if l == None:
- notfound = 'path'
-
- l, dummy = getprefpath(PATH_STRINGS_ID)
- if l == None:
- message('Cannot find any sys.path resource! (Old python?)')
- sys.exit(0)
-
- fss, dr, fss_changed = getprefdir(OVERRIDE_DIRECTORY_ID)
- if fss == None:
- if notfound:
- notfound = notfound + ', directory'
- else:
- notfound = 'directory'
- fss, dummy, dummy2 = getprefdir(DIRECTORY_ID)
- if fss == None:
- fss = macfs.FSSpec(os.getcwd())
- fss_changed = 1
-
- options, opr = getoptions(OVERRIDE_OPTIONS_ID)
- if not opr:
- if notfound:
- notfound = notfound + ', options'
- else:
- notfound = 'options'
- options, dummy = getoptions(OPTIONS_ID)
- saved_options = options[:]
-
- creator, type, delaycons, gusi_opr = getgusioptions(OVERRIDE_GUSI_ID)
- if not gusi_opr:
- if notfound:
- notfound = notfound + ', GUSI options'
- else:
- notfound = 'GUSI options'
- creator, type, delaycons, gusi_opr = getgusioptions(GUSI_ID)
- saved_gusi_options = creator, type, delaycons
-
- dummy = dummy2 = None # Discard them.
-
- if notfound:
- message('Warning: initial %s taken from system-wide defaults'%notfound)
- # Let the user play away
- print 'DBG interaction'
- result = interact(l, fss, (options, creator, type, delaycons), name)
-
- # See what we have to update, and how
- if result == None:
- sys.exit(0)
-
- pathlist, nfss, (options, creator, type, delaycons) = result
- if nfss != fss:
- fss_changed = 1
-
- if fss_changed:
- alias = nfss.NewAlias()
- if dr:
- dr.data = alias.data
- dr.ChangedResource()
- else:
- dr = Resource(alias.data)
- dr.AddResource('alis', OVERRIDE_DIRECTORY_ID, '')
-
- if pathlist != l:
- if pathlist == []:
- if sr.HomeResFile() == app_handle:
- sr.RemoveResource()
- elif sr and sr.HomeResFile() == app_handle:
- sr.data = listtores(pathlist)
- sr.ChangedResource()
- else:
- sr = Resource(listtores(pathlist))
- sr.AddResource('STR#', OVERRIDE_PATH_STRINGS_ID, '')
-
- if options != saved_options:
- newdata = reduce(lambda x, y: x+chr(y), options, '')
- if opr and opr.HomeResFile() == app_handle:
- opr.data = newdata
- opr.ChangedResource()
- else:
- opr = Resource(newdata)
- opr.AddResource('Popt', OVERRIDE_OPTIONS_ID, '')
-
- if (creator, type, delaycons) != saved_gusi_options:
- newdata = setgusioptions(gusi_opr, creator, type, delaycons)
- id, type, name = gusi_opr.GetResInfo()
- if gusi_opr.HomeResFile() == app_handle and id == OVERRIDE_GUSI_ID:
- gusi_opr.data = newdata
- gusi_opr.ChangedResource()
- else:
- ngusi_opr = Resource(newdata)
- ngusi_opr.AddResource('GU\267I', OVERRIDE_GUSI_ID, '')
-
- CloseResFile(app_handle)
-
- def main():
- try:
- h = OpenResFile('EditPythonPrefs.rsrc')
- except Res.Error:
- pass # Assume we already have acces to our own resource
-
- if len(sys.argv) <= 1:
- edit_preferences()
- else:
- for appl in sys.argv[1:]:
- edit_applet(appl)
-
-
- if __name__ == '__main__':
- main()
-